﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Bookworm.Core
{
    public partial class EbookInfoXml
    {
        public static explicit operator EbookInfo(EbookInfoXml ebookInfoXml)
        {
            var ebook = new EbookInfo();

            ebook.Title = ebookInfoXml.title;
            ebook.Description = ebookInfoXml.description;
            ebook.Isbn10 = ebookInfoXml.isbn10;
            ebook.Isbn13 = ebookInfoXml.isbn13;
            ebook.Publisher = ebookInfoXml.publisher;
            ebook.PublishDate = ebookInfoXml.publishdate;
            ebook.Language = ebookInfoXml.language;
            ebook.Rating = ebookInfoXml.rating;

            if (Enum.IsDefined(typeof(Format), ebookInfoXml.format))
                ebook.Format = (Format)Enum.Parse(typeof(Format), ebookInfoXml.format, true);
            else
            {
                ebook.CustomFormat = ebookInfoXml.format;
                ebook.Format = Format.Other;
            }

            ebook.Subtitles.CopyFromArray(ebookInfoXml.subtitles);
            ebook.Categories.CopyFromArray(ebookInfoXml.categories);
            ebook.Tags.CopyFromArray(ebookInfoXml.tags);

            ebook.Authors.CopyFromArray(ebookInfoXml.authors, author => (Author)author);
            ebook.Links.CopyFromArray(ebookInfoXml.links,link =>(Link)link);
            ebook.Images.CopyFromArray(ebookInfoXml.images,image =>(Image)image);

            return ebook;
        }

        public static explicit operator EbookInfoXml(EbookInfo ebook)
        {
            var ebookInfoXml = new EbookInfoXml();

            ebookInfoXml.title = ebook.Title;
            ebookInfoXml.description = ebook.Description;
            ebookInfoXml.rating = ebook.Rating;
            ebookInfoXml.isbn10 = ebook.Isbn10;
            ebookInfoXml.isbn13 = ebook.Isbn13;
            ebookInfoXml.publisher = ebook.Publisher;           
            if(ebook.PublishDate.HasValue)
            {
                ebookInfoXml.publishdate = ebook.PublishDate.Value;
                ebookInfoXml.publishdateFieldSpecified = true;
            }
            ebookInfoXml.language = ebook.Language;
            if(ebook.PageCount.HasValue)
            {
                ebookInfoXml.pagecount = ebook.PageCount.Value;
                ebookInfoXml.pagecountFieldSpecified = true;
            }            
            if (ebook.Format == Format.Other && ebook.CustomFormat != null)
                ebookInfoXml.format = ebook.CustomFormat;
            else
                ebookInfoXml.format = Enum.GetName(typeof(Format), ebook.Format);

            ebookInfoXml.subtitles = ebook.Subtitles.ToArray();
            ebookInfoXml.categories = ebook.Categories.ToArray();
            ebookInfoXml.tags = ebook.Tags.ToArray();
            ebookInfoXml.authors = ebook.Authors.ToArray(author => (ebookAuthor)author);
            ebookInfoXml.links = ebook.Links.ToArray(link => (ebookLink)link);
            ebookInfoXml.images = ebook.Images.ToArray(image => (ebookImage)image);
            return ebookInfoXml;
        }
    }

    public partial class ebookAuthor
    {
        public static explicit operator Author(ebookAuthor ebookAuthor)
        {
            var author = new Author();
            author.Name = ebookAuthor.Value;
            author.Type = (AuthorType)Enum.Parse(typeof(AuthorType), ebookAuthor.type, true);
            author.Description = ebookAuthor.description;
            return author;
        }

        public static explicit operator ebookAuthor(Author author)
        {
            var ebookAuthor = new ebookAuthor();
            ebookAuthor.Value = author.Name;
            ebookAuthor.type = author.Type.ToString();
            ebookAuthor.description = author.Description;
            return ebookAuthor;
        }
    }

    public partial class ebookLink
    {
        public static explicit operator Link(ebookLink ebookLink)
        {
            var link = new Link();
            link.Url = ebookLink.Value;
            link.Type = (LinkType)Enum.Parse(typeof(LinkType), ebookLink.type, true);
            return link;
        }

        public static explicit operator ebookLink(Link link)
        {
            var ebookLink = new ebookLink();
            ebookLink.Value = link.Url;
            ebookLink.type = link.Type.ToString();
            return ebookLink;
        }        
    }

    public partial class ebookImage
    {
        public static explicit operator Image(ebookImage ebookImage)
        {
            var image = new Image();
            image.Path = ebookImage.Value;
            image.Type = (ImageType)Enum.Parse(typeof(ImageType), ebookImage.type, true);
            image.Width = ebookImage.width;
            image.Height = ebookImage.height;
            return image;
        }

        public static explicit operator ebookImage(Image image)
        {
            var ebookImage = new ebookImage();
            ebookImage.Value = image.Path;
            ebookImage.type = image.Type.ToString();
            if(image.Width.HasValue)
            {
                ebookImage.width = image.Width.Value;
                ebookImage.widthFieldSpecified = true;
            }
            if(image.Height.HasValue)
            {
                ebookImage.height = image.Height.Value;
                ebookImage.heightFieldSpecified = true;
            }
            return ebookImage;            
        }
    }

    internal static class ConverterExtender
    {
        internal static void CopyFromArray<T>(this IList<T> list, T[] array)
        {
            if (array == null || array.Length == 0)
                return;

            for (int i = 0; i < array.Length; i++)
                list.Add(array[i]);
        }

        internal static void CopyFromArray<TInput, TOutput>(this IList<TOutput> list, TInput[] array, Converter<TInput, TOutput> converter)
        {
            if (array == null || array.Length == 0)
                return;

            for (int i = 0; i < array.Length; i++)
                list.Add(converter(array[i]));
        }

        internal static TOutput[] ToArray<TInput, TOutput>(this IList<TInput> source, Converter<TInput, TOutput> converter)
        {
            var output = new TOutput[source.Count];
            for (int i = 0; i < source.Count; i++)
                output[i] = converter(source[i]);
            return output;
        }
    }
}
